package org.afei.ioc.handler;


import org.afei.ioc.annotation.Bean;
import org.afei.ioc.annotation.Param;
import org.afei.ioc.annotation.Service;
import org.afei.ioc.entity.BeanEntity;
import org.afei.ioc.entity.ParamEntity;
import org.afei.ioc.entity.ServiceEntity;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;

/**
 * 元数据处理器装饰对象的具体实现（处理注解）
 * 根据包名来获取此包下所有的类名及其实例
 *
 * @author afei
 * @date 17-5-25.
 */
public class DefaultAnnotationHandler extends
        HandlerDecorator {


    @Override
    public Map<String, Object> convert(String packName) {
        //System.out.println("这是一个Annotation的handler");
        Map<String, Object> map = super.convert(packName);

        Map<String, Object> beanMap = new HashMap<>();
        String packageName = packName;
        String packageDirName = packageName.replace(".", "/");
        Enumeration<URL> dirs;
        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

            //迭代此 Enumeration
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();
                File file = new File(url.getFile());
                //把此目录下的所有文件列出
                String[] classes = file.list();
                //循环此数组，并把.class去掉
                for (String className : classes) {
                    className = className.substring(0, className.length() - 6);
                    //拼接上包名，变成全限定名
                    String qName = packageName + "." + className;
                    //如有需要，把每个类生实一个实例
                    Object obj = Class.forName(qName).newInstance();

                    //如果这个类有@Bean注解，则将其返回。
                    boolean flag = obj.getClass().isAnnotationPresent(Bean.class);

                    //----------------处理类注解-----begin-----------------
                    if (flag) {
                        Bean bean = obj.getClass().getAnnotation(Bean.class);
                        //System.out.println("描述bean的名称:"+bean.name());
                        //System.out.println("描述bean的类型:"+qName);

                        Method[] methods = obj.getClass().getMethods();
                        List<ServiceEntity> serviceEntityList = new ArrayList<>();

                        //------------处理方法注解----begin------------
                        for (Method method : methods) {

                            if (method.getAnnotation(Service.class) == null) {
                                continue;
                            }

                            //System.out.println("方法名称:" +  method.getName());
                            Service service = method.getAnnotation(Service.class);

                            //-----------处理参数注解----begin---------------
                            Class<?>[] parameterTypes = method.getParameterTypes();
                            Annotation[][] annotations = method.getParameterAnnotations();
                            List<ParamEntity> paramEntityList = new ArrayList<>();
                            if (annotations.length > 0) {
                                for (int i = 0; i < annotations.length; i++) {
                                    for (int j = 0; j < annotations[i].length; j++) {
                                        Param param = (Param) annotations[i][j];
                                        //System.out.println("参数注解的名称"+param.name());
                                        //System.out.println("参数的类型"+parameterTypes[j].getName());
                                        paramEntityList.add(new ParamEntity(param.name(), parameterTypes[j].getName()));
                                    }
                                }
                            }
                            //-----------处理参数注解----end---------------

                            serviceEntityList.add(new ServiceEntity(service.name(), method.getName(), paramEntityList));
                        }
                        //------------处理方法注解----end------------


                        beanMap.put(bean.name(), new BeanEntity(bean.name(), qName, serviceEntityList));
                    }

                    //----------------处理类注解-----end-----------------
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        if (map != null && map.size() != 0) {
            beanMap.putAll(map);
        }

        return beanMap;
    }

}
